package com.HeJing.数组的相关算法操作;

/**
 * ClassName: 数组相关算法操作
 * Package: com.HeJing.数组的相关算法操作
 * Description:
 *
 * @Author: HeJing
 * @Create: 2023-03-19 14:48
 * @Version: 1.0
 */
public class 数组相关基本操作 {
    public static void main(String[] args){
        /*
        *
        *
        * */
        test();

    }

    public static void test(){

        // 调用求取数组特征值的函数
        // getArrayEigenValue();

        // 数组复制案例: 杨辉三角
        // yangHui(10);

        //回形数案例:
        // HuiXingNumber(5);

        // 数组元素反转操作的案例:
        // arrayReverse();

        // 数组的扩容操作:
        // arrExpansion();

        // 数组的缩容操作:
        arrReduction(4);
    }

    // 数组打印操作:
    public static void printArr(int[] arr){
        for(int i = 0; i < arr.length - 1; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println(arr[arr.length - 1]);
    }

    // 求取数组特征值(平均值，最大最小值等)
    public static void getArrayEigenValue(){
        // 动态初始化创建数组:
        int[] arr = new int[10];
        // for循环赋值
        for(int i = 0; i < arr.length; i++){
            arr[i] = (int)(Math.random()*(99 - 10 + 1)) + 10;   // 随机值范围 10-100
        }

        // 求最大值/最小值/平均值/总和:
        int maxValue = arr[0];
        int count = arr[0];

        for(int i = 1; i < arr.length; i++){
            System.out.print(arr[i - 1] + " ");
            if(maxValue < arr[i]){
                maxValue = arr[i];
            }
            count += arr[i];
        }
        System.out.println(arr[arr.length - 1]);
        System.out.println("最大值是: " + maxValue);
        System.out.println("总和是: " + count);
        System.out.println("平均值是: " + count / arr.length);
    }

    // 数组的赋值操作；案例: 杨辉三角的打印
    public static void yangHui(int num){
        /*
        * 案例:
        * 使用二维数组打印一个10行杨辉三角
        * 提示:
        *   1、第一行有1个元素，第n行有n个元素
        *   2、每1行的第一个元素和最后一个元素都是1
        *   3、从第三行开始，对于非第一个元素的非最后一个元素的元素，有: yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j]
        * */
        int[] yangHui[] = new int[num][];
        yangHui[0] = new int[]{1};      // 第一行直接赋值
        yangHui[1] = new int[]{1, 1};   // 第二行直接赋值

        // 开始初始化杨辉三角
        for(int i = 2; i < num; i++){
            yangHui[i] = new int[i + 1];   // 为杨辉三角后续的每一行分配空间
            yangHui[i][0] = 1;    // 每一行的第一个元素为1
            yangHui[i][yangHui[i].length - 1] = 1;  // 每一行的最后一个元素值为1
            // 为每一行除了首末元素之外的元素赋值
            for(int j = 1; j < i; j++){
                yangHui[i][j] = yangHui[i - 1][j - 1] + yangHui[i - 1][j];
            }


        }

        // 打印验证:
        for(int i = 0; i < yangHui.length; i++){
            for(int j = 0; j < i + 1; j++){
                System.out.print(yangHui[i][j] + " ");
            }
            System.out.println();
        }
    }

    // 数组的赋值操作: 案例: 回形数
    // https://blog.csdn.net/Peter__Li/article/details/103430051
    public static void HuiXingNumber(int n){
        /*
        *   从键盘输入一个整数n(1-20), 以该数字为矩阵的大小，把1,2,3,...n*n的数字按照顺时针螺旋的形式填入其中
        *   例如:
        *   输入数字2，则程序输出:
        *   1 2
        *   4 3
        *
        *   输入数字3, 则程序输出:
        *   1 2 3
        *   8 9 4
        *   7 6 5
        * */

        // 思路来自: https://blog.csdn.net/Peter__Li/article/details/103430051

        int[][] numArr = new int[n][n];

        int count = n * n; //s表示该矩阵的总数目

        int k = 1; //k变量表示往哪个方向赋值  初始化从向右开始
        int i = 0, j = 0; //i表示数组的纵坐标  j表示数组的横坐标
        for (int m = 1; m <= count; m++) {  //循环的次数刚好是矩阵的总数目
            if (k == 1) {   //向右    赋值限制条件：如果横坐标小于输入的矩阵纵横数并且值是默认值0就给它赋值
                if (j < n && numArr[i][j] == 0) {
                    numArr[i][j++] = m;
                } else {    //如果不是
                    k = 2;  //表示改变方向赋值  向下
                    i++;    //每次方向赋值完 要换一行方便下个判断赋值 所以i自增1 保证下次循环i下标是正确的
                    j--;    //每次方向赋值完 要帮上面j++多运行的一次自减1 保证下次循环j下标是正确的
                    m--;    //每次方向赋值完 进入else语句都要自减1 保证下次循环m的赋值数是正确的
                }
            } else if (k == 2) {    //向下   以下同理
                if (i < n && numArr[i][j] == 0) {
                    numArr[i++][j] = m;
                } else {
                    k = 3;
                    i--;
                    j--;
                    m--;
                }
            } else if (k == 3) {    //向左
                if (j >= 0 && numArr[i][j] == 0) {
                    numArr[i][j--] = m;
                } else {
                    k = 4;
                    i--;
                    j++;
                    m--;
                }
            } else if (k == 4) {    //向上
                if (i >= 0 && numArr[i][j] == 0) {
                    numArr[i--][j] = m;
                } else {
                    k = 1;
                    i++;
                    j++;
                    m--;
                }
            }
        }

        // 遍历
        for (int[] anArr : numArr) {
            for (int anAnArr : anArr) {
                System.out.print(anAnArr + "\t");
            }
            System.out.println();
        }

    }


    // 数组的复制操作: 深拷贝? 有数组array1
    /*
    *   赋值操作:
    *       -> int[] array2 = array1
    *       -> 说明: 数组array2 和 数组array1指向同一块内存地址，删改操作会互相影响，只能称之为  "赋值"
    *   复制操作:
    *       -> int[] array2 = new int[array1.length]
    *       -> for(int i = 0; i < array1.length; i++){
    *       ->      array2[i] = array1[i];
    *       -> }
    *       -> 说明: 此时数组array2 和 数组array1指向的内存并不相同，删改操作不会相互影响，可称之为 "复制"
    * */


    // 数组元素的反转操作:
    public static void arrayReverse(){

        // 建立一个随机数组:
        int[] arr = new int[10];
        for(int i = 0; i < arr.length; i++){
            arr[i] = (int)(Math.random()*(100 - 10 + 1)) + 10;  // 数组取值范围: 10-100
        }
        // 打印未反转前的数组:
        System.out.print("反转之前的数组元素为: ");
        printArr(arr);

        // 进行数组反转操作:
        for(int i = 0, j = arr.length - 1; i < j; i++, j--){
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        // 打印反转之后的数组元素:
        System.out.print("反转之后的数组元素为: ");
        printArr(arr);
    }


    // 数组的扩容操作:
    public static void arrExpansion(){
        int[] arr = new int[]{1, 2, 3, 4, 5};

        // 扩容一倍容量
        int[] newArr = new int[arr.length << 1];

        // 将原有数组中的元素复制到新的数组中
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = arr[i];
        }
        // 将10，20，30三个数据添加到新数组中
        newArr[arr.length] = 10;
        newArr[arr.length + 1] = 20;
        newArr[arr.length + 2] = 30;

        arr = newArr;

        // 打印:
        for (int i = 0; i < arr.length - 1; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println(arr[arr.length - 1]);

    }

    // 数组的缩容:
    // 现有数组 int[] arr = {1, 2, 3,4, 5, 6, 7}, 现需要删除数组中索引为4的元素
    public static void arrReduction(int index){
        int[] arr = {1, 2, 3, 4, 5, 6, 7};

        // 方式1: 不新建数组
        int deleteIndex = index;
        for (int i = deleteIndex; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        // 修改最后一个元素
        arr[arr.length - 1] = 0;  // 设为默认值

        // 遍历数组
        printArr(arr);

        // 方式2: 新建数组
        int[] arr1 = {1, 2, 3, 4, 5, 6, 7};
        int[] newArr = new int[arr1.length - 1];
        for (int i = 0; i < deleteIndex; i++) {
            newArr[i] = arr1[i];
        }
        for(int i = deleteIndex; i < arr1.length - 1; i++){
            newArr[i] = arr1[i + 1];
        }
        arr1 = newArr;
        printArr(arr1);
    }

}



















